package com.mdtx.database;

import com.mdtx.database.utils.DataBaseHelper;
import com.mdtx.entity.ClassAttribute;
import com.mdtx.entity.DbConfig;
import com.mdtx.entity.FieldAttribute;
import com.mdtx.utils.ConvertUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据库操作类
 *
 * @author 猫啊
 * @create 2018-06-12 17:45
 **/
public abstract  class AbstractDatabaseOperation implements DataBaseQuery{


    protected  DbConfig dbConfig;

    protected DataBaseDriver driver;

    protected DataBaseDriver initDataBaseDriver(){
        driver = Cache.connectCache.get(this.getDbType());

        if(driver == null){

            driver = new DataBaseDriver();
            driver.setDriver(this.getDbDriverType());
            driver.setUser(dbConfig.getUsername());
            driver.setPassword(dbConfig.getPassword());
            driver.setDbInfo("remarks", "true");
            driver.setDbInfo("useInformationSchema", "true");
            Cache.connectCache.put(this.getDbType(),driver);
        }
        //数据库可能变动
        driver.setUrl(configJdbcUrl());


        return driver;
    }


    public void configDb(String db){

        this.dbConfig.setDb(db);

    }



    protected abstract String configJdbcUrl();

    protected abstract String getDbType();

    protected abstract String getDbDriverType();


    @Override
    public List<String> queryAllDatabases(String sql) {
        PreparedStatement state = null;
        ResultSet resultSet = null;
        Connection connection = null;
        try {
            connection = DataBaseHelper.getConnection(initDataBaseDriver());
            state = connection.prepareStatement(sql);
            resultSet = state.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            List<String> dbList = new ArrayList<String>();
            while (resultSet.next()) {

                for (int i = 0; i < metaData.getColumnCount(); i++) {
                    dbList.add(resultSet.getObject(i+1)+"");
                }

            }

            return dbList;

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DataBaseHelper.releaseConn(connection,state,resultSet);
        }
        return null;
    }

    @Override
    public List<ClassAttribute> queryDatabaseAllTables(String db) {
        ResultSet resultSet = null;
        Connection connection = null;
        List<ClassAttribute> tableList = new ArrayList<ClassAttribute>();
        try {
            connection = DataBaseHelper.getConnection(initDataBaseDriver());
            resultSet = DataBaseHelper.getTables(connection,null,db,"%",new String[]{"TABLE"});
            ClassAttribute table = null;
            while (resultSet.next()) {
                table = new ClassAttribute();
                String tableName=resultSet.getString("TABLE_NAME");
                String remarkes = resultSet.getString("REMARKS");
                table.setTableName(tableName);
                table.setComment(remarkes);
                tableList.add(table);

            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DataBaseHelper.releaseConn(connection,null,resultSet);
        }

        return tableList;
    }

    @Override
    public List<FieldAttribute> queryTableColumns(String db, String table) {
        ResultSet colRet= null;
        Connection connection = null;
        List<FieldAttribute> fieldList = new ArrayList<FieldAttribute>();
        try {
            connection = DataBaseHelper.getConnection(initDataBaseDriver());
            colRet = DataBaseHelper.getAllColumns(connection,null,db,table,"%");
            FieldAttribute column = null;
            while (colRet.next()) {
                column = new FieldAttribute();
                column.setDbType(this.getDbType());
                column.setColumnName(colRet.getString("COLUMN_NAME"));
                column.setTypeName(colRet.getString("TYPE_NAME"));
                column.setColumnSize(colRet.getInt("COLUMN_SIZE"));
                column.setDecimalDigits(colRet.getInt("DECIMAL_DIGITS"));
                column.setNullAble(colRet.getInt("NULLABLE")==0?true:false);
                column.setRemark(colRet.getString("REMARKS"));
                fieldList.add(column);

            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DataBaseHelper.releaseConn(connection,null,colRet);
        }

        return fieldList;
    }

    @Override
    public List<Map<String,String>> queryTablePrimaryKeys(String db, String table) {
        ResultSet colRet= null;
        Connection connection = null;
        List<Map<String,String>> keyList = new ArrayList<Map<String,String>>();

        try {
            connection = DataBaseHelper.getConnection(initDataBaseDriver());
            colRet = DataBaseHelper.getPrimaryKeys(connection,null,"$",table);
            Map<String,String> m = null;
            String v = "";
            while (colRet.next()){
                m=new HashMap<String, String>();
                v = colRet.getString("COLUMN_NAME").toLowerCase();
                m.put("col",v);
                m.put("fil", ConvertUtil.toCamelCasing(v,false));
                keyList.add(m);
            }


        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DataBaseHelper.releaseConn(connection,null,colRet);
        }

        return keyList;
    }

    public DbConfig getDbConfig() {
        return dbConfig;
    }

    public void setDbConfig(DbConfig dbConfig) {
        this.dbConfig = dbConfig;
    }
}
